브리지 패턴
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
브리지 패턴은 추상화와 구현을 분리하여 유연성을 높이는 디자인 패턴이다. 이 패턴은 추상화 계층과 구현 계층을 독립적으로 변경하고 확장할 수 있게 해준다. 브리지 패턴은 추상화(Abstraction)와 구현(Implementor)의 두 계층으로 구성되며, 추상화는 구현 객체에 대한 참조를 유지한다. 이 패턴은 특히, 여러 종류의 추상화와 여러 종류의 구현이 존재하여 이들 간의 조합이 필요한 경우 유용하다. 브리지 패턴은 시스템의 유연성을 높이고, 코드 중복을 줄이며, 유지보수성을 향상시키는 데 기여한다. 예를 들어, 식기류의 종류와 재질을 독립적으로 확장해야 하는 상황에서 브리지 패턴을 적용하여 클래스 설계를 개선할 수 있다.
더 읽어볼만한 페이지
- 소프트웨어 디자인 패턴 - 모델-뷰-컨트롤러
모델-뷰-컨트롤러(MVC)는 소프트웨어 디자인 패턴으로, 응용 프로그램을 모델, 뷰, 컨트롤러 세 가지 요소로 분리하여 개발하며, 사용자 인터페이스 개발에서 데이터, 표현 방식, 사용자 입력 처리를 분리해 유지보수성과 확장성을 높이는 데 기여한다. - 소프트웨어 디자인 패턴 - 스케줄링 (컴퓨팅)
스케줄링은 운영 체제가 시스템의 목적과 환경에 맞춰 작업을 관리하는 기법으로, 장기, 중기, 단기 스케줄러를 통해 프로세스를 선택하며, CPU 사용률, 처리량 등을 기준으로 평가하고, FCFS, SJF, RR 등의 알고리즘을 사용한다.
| 브리지 패턴 | |
|---|---|
| 개요 | |
![]() | |
| 유형 | 구조적 패턴 |
| 목적 | 추상 인터페이스와 구현을 분리하여 독립적으로 다양화 |
| 별칭 | 핸들러/바디 |
| 동기 | |
| 문제 | 단일 클래스 계층 구조에서 인터페이스와 구현을 결합하면 유연성과 재사용성이 저하될 수 있다. 다양한 구현을 지원하기 위해 여러 서브클래스를 생성하면 계층 구조가 복잡해지고 유지 관리가 어려워진다. |
| 해결책 | 추상 인터페이스와 구현을 별도의 클래스 계층 구조로 분리한다. 추상 인터페이스는 클라이언트가 상호 작용하는 고수준 인터페이스를 정의한다. 구현은 추상 인터페이스를 지원하는 저수준 세부 정보를 제공한다. 브리지 패턴은 추상 인터페이스와 구현 간의 연결을 설정하여 독립적인 변경을 가능하게 한다. |
| 구조 | |
| 추상화 (Abstraction) | 고수준 제어 인터페이스를 정의한다. 구현체 객체에 대한 참조를 유지한다. |
| 정제된 추상화 (Refined Abstraction) | 추상화에서 파생되어 추가 기능을 제공한다. |
| 구현체 (Implementor) | 구현에 대한 인터페이스를 정의한다. 이 인터페이스는 추상화 인터페이스의 작업을 구현하는 데 필요한 기본 작업을 정의한다. |
| 구체적인 구현체 (Concrete Implementor) | 구현체 인터페이스를 구현하고 특정 플랫폼 또는 기술에 대한 구현을 제공한다. |
| 적용 가능성 | |
| 경우 | 클래스와 그 구현 간에 1:1 관계를 피하고 싶을 때. 추상화와 구현 모두 독립적으로 확장되어야 하는 경우. 구현체의 변경 사항이 클라이언트에 영향을 미치지 않아야 하는 경우. |
| 장점 | |
| 효과 | 추상화와 구현을 분리하여 독립적인 개발 및 확장을 가능하게 한다. 구현 세부 사항으로부터 클라이언트를 보호하여 결합도를 줄인다. 다양한 구현을 런타임에 선택하거나 교체할 수 있는 유연성을 제공한다. |
| 단점 | |
| 한계 | 디자인에 복잡성을 더할 수 있다. 특히 단순한 시스템에서는 불필요할 수 있다. 새로운 추상화 또는 구현체를 추가하려면 인터페이스를 신중하게 설계해야 한다. |
| 관련 패턴 | |
| 연관된 패턴 | 어댑터 패턴: 기존 클래스를 사용하도록 인터페이스를 변경한다. 팩토리 메서드 패턴: 객체 생성을 서브클래스에 위임한다. 전략 패턴: 알고리즘을 캡슐화하고 런타임에 선택할 수 있게 한다. |
| 구현 | |
| 구현 고려 사항 | 올바른 추상화 및 구현 인터페이스를 식별한다. 구현체 객체에 대한 참조를 추상화 클래스에 유지한다. 클라이언트가 추상화 인터페이스와 상호 작용하도록 한다. |
| 예제 | |
| 예시 | GUI 프레임워크 (창, 버튼 등) 데이터베이스 드라이버 운영 체제 이식성 계층 |
| 사용 사례 | |
| 사용 예 | 다양한 플랫폼에서 실행되는 응용 프로그램 다양한 데이터베이스를 지원하는 응용 프로그램 다양한 그래픽 형식을 지원하는 응용 프로그램 |
2. 구조
브리지 디자인 패턴은 유연하고 재사용 가능한 객체 지향 소프트웨어를 설계하기 위한 23가지 GoF 디자인 패턴 중 하나이다. 이 패턴은 구현, 변경, 테스트 및 재사용이 더 쉬운 객체를 만드는 데 도움을 준다.[1]
브리지 디자인 패턴은 다음 문제들을 해결할 수 있다.[1]
- 추상화와 구현은 서로 독립적으로 정의되고 확장되어야 한다.
- 추상화와 구현 간의 컴파일 타임 바인딩은 피해야 하며, 런타임에 구현을 선택할 수 있어야 한다.
서브클래싱을 사용하면 서로 다른 서브클래스들이 추상 클래스를 다르게 구현한다. 그러나 구현은 컴파일 타임에 추상화에 바인딩되어 런타임에는 변경할 수 없다.
브리지 디자인 패턴은 추상화(`Abstraction`)와 구현(`Implementor`)을 별도의 클래스 계층 구조로 분리하여 런타임에 `Abstraction`을 `Implementor` 객체로 구성할 수 있도록 한다.[1]
브리지 패턴이 적용된 클래스 구조의 예시는 다음과 같다.
이 클래스 다이어그램에서 Dishware (식기)에서 파생되는 상속 관계는 식기의 종류뿐이며, 재질에 관한 정보는 Material (소재) 클래스에 위임하고 있다. 이 구조를 통해 종류와 재질을 각각 독립적으로 확장할 수 있으며, 클래스의 수도 줄일 수 있다.
2. 1. UML 클래스 및 시퀀스 다이어그램

위의 UML 클래스 다이어그램에서 추상화(
Abstraction)는 단일 상속 계층 구조에서 통상적으로 구현되지 않는다. 대신 추상화(Abstraction)에 대한 하나의 계층 구조와 구현(Implementor)에 대한 별도의 계층 구조가 있어 두 계층 구조를 서로 독립적으로 만든다. Abstraction 인터페이스(operation())는 Implementor 인터페이스(imp.operationImp())에 위임하여 구현된다.UML 시퀀스 다이어그램은 런타임 상호 작용을 보여준다.
Abstraction1 객체는 구현을 Implementor1 객체에 위임한다 (Implementor1에서 operationImp()을 호출하여). 그러면 Implementor1은 작업을 수행하고 Abstraction1로 반환한다.2. 2. 클래스 구성 요소
- 추상화 (Abstraction): 추상 인터페이스를 정의하고, 구현자에 대한 참조를 유지한다.[1]
- 정제된 추상화 (Refined Abstraction): 추상화(Abstraction)를 확장하여 구체적인 기능을 추가한다.[1]
- 구현자 (Implementor): 구현 클래스에 대한 인터페이스를 정의한다.[1]
- 구체적인 구현자 (Concrete Implementor): 구현자(Implementor) 인터페이스를 실제로 구현한다.[1]
3. 문제 해결 및 장점
브리지 디자인 패턴은 유연하고 재사용 가능한 객체 지향 소프트웨어를 설계하는 데 사용되는 GoF 디자인 패턴 중 하나이다.[1] 이 패턴은 구현, 변경, 테스트 및 재사용이 더 쉬운 객체를 만드는 데 도움을 준다.
브리지 디자인 패턴은 다음과 같은 문제를 해결한다.
- 추상화와 구현을 서로 독립적으로 정의하고 확장할 수 있어야 한다.
- 추상화와 구현 간의 컴파일 타임 바인딩(고정적인 관계)을 피하고, 런타임에 구현을 선택할 수 있어야 한다.
서브클래싱을 사용하면 서로 다른 서브클래스가 추상 클래스를 다르게 구현한다. 하지만 구현은 컴파일 타임에 추상화에 고정되므로 런타임에는 변경할 수 없다.
브리지 디자인 패턴은 다음과 같은 해결책을 제시한다.
- 추상화(`Abstraction`)와 구현(`Implementor`)을 별도의 클래스 계층으로 분리한다.
- `Abstraction`을 `Implementor` 객체에 위임하여 구현한다.
이렇게 하면 런타임에 `Abstraction`을 `Implementor` 객체로 구성할 수 있게 된다.
예를 들어, 식기(Dishware) 클래스에서 접시(Plate)와 그릇(Bowl) 클래스가 파생되고, 더 나아가 나무 접시(WoodenPlate), 유리 접시(GlassPlate), 나무 그릇(WoodenBowl), 유리 그릇(GlassBowl)이 파생되는 클래스 계층을 생각해 보자.
이 구조는 다음과 같은 문제를 갖는다.
- 새로운 재질(예: 플라스틱)을 지원하려면 Plate와 Bowl 각각을 상속해야 한다.
- 새로운 종류의 식기(예: 컵)를 추가하려면 WoodenCup과 GlassCup을 모두 만들어야 한다.
- WoodenPlate과 WoodenBowl, GlassPlate과 GlassBowl처럼 같은 재질의 식기는 비슷한 코드를 가질 수 있지만, 상속 때문에 개별적으로 정의해야 하므로 코드 중복이 발생한다.
이러한 문제는 클래스 계층 안에 '식기의 종류'와 '식기의 재질'이라는 여러 상속 관계가 섞여 있기 때문에 발생한다.
브리지 패턴을 적용하면 이 구조를 다음과 같이 개선할 수 있다.
이 다이어그램에서는 Dishware에서 파생되는 상속 관계는 식기의 종류뿐이며, 재질에 관한 정보는 Material (소재) 클래스에 위임한다. 따라서 종류와 재질을 독립적으로 확장할 수 있고, 클래스 수도 줄일 수 있다.
4. 코드 예제
다음은 여러 프로그래밍 언어로 구현된 브리지 패턴 예제를 보여준다.
각 예제는 `DrawingAPI` 인터페이스와 이를 구현하는 `DrawingAPI1`, `DrawingAPI2` 클래스를 정의한다. `Shape` 추상 클래스는 `DrawingAPI`를 사용하여 그림을 그리는 기능을 제공하며, `CircleShape` 클래스는 `Shape`를 상속받아 구체적인 원을 그린다.
- C#: C# 코드 예제와 출력 결과가 소스에 포함되어 있다.
- C++: C++ 코드 예제와 출력 결과가 소스에 포함되어 있다.
- Go: Go 코드 예제가 소스에 포함되어 있다.
- Python: Python 코드 예제가 소스에 포함되어 있다.
- 기타 언어 (Crystal, PHP, Scala): Crystal, PHP, Scala 코드 예제가 소스에 포함되어 있다.
4. 1. Java
다음은 계좌 연산을 해당 연산의 로깅과 분리하는 은행 계좌를 정의하는 Java 프로그램이다.```java
// 로거는 info와 warning의 두 가지 구현을 가지고 있습니다.
@FunctionalInterface
interface Logger {
void log(String message);
static Logger info() {
return message -> System.out.println("info: " + message);
}
static Logger warning() {
return message -> System.out.println("warning: " + message);
}
}
abstract class AbstractAccount {
private Logger logger = Logger.info();
public void setLogger(Logger logger) {
this.logger = logger;
}
// 로깅 부분은 Logger 구현에 위임됩니다.
protected void operate(String message, boolean result) {
logger.log(message + " result " + result);
}
}
class SimpleAccount extends AbstractAccount {
private int balance;
public SimpleAccount(int balance) {
this.balance = balance;
}
public boolean isBalanceLow() {
return balance < 50;
}
public void withdraw(int amount) {
boolean shouldPerform = balance >= amount;
if (shouldPerform) {
balance -= amount;
}
operate("withdraw " + amount, shouldPerform);
}
}
public class BridgeDemo {
public static void main(String[] args) {
SimpleAccount account = new SimpleAccount(100);
account.withdraw(75);
if (account.isBalanceLow()) {
// 런타임에 Logger 구현을 변경할 수도 있습니다.
account.setLogger(Logger.warning());
}
account.withdraw(10);
account.withdraw(100);
}
}
```
출력 결과는 다음과 같다.
```
info: withdraw 75 result true
warning: withdraw 10 result true
warning: withdraw 100 result false
4. 2. C#
csharp// "Implementor" 인터페이스
interface IDrawingAPI
{
void DrawCircle(double x, double y, double radius);
}
// "ConcreteImplementor" 1/2
class DrawingAPI1 : IDrawingAPI
{
public void DrawCircle(double x, double y, double radius)
{
Console.WriteLine("API1.circle at {0}:{1} radius {2}", x, y, radius);
}
}
// "ConcreteImplementor" 2/2
class DrawingAPI2 : IDrawingAPI
{
public void DrawCircle(double x, double y, double radius)
{
Console.WriteLine("API2.circle at {0}:{1} radius {2}", x, y, radius);
}
}
// "Abstraction" 인터페이스
interface IShape
{
void Draw(); // 하위 수준 (구현에 특화)
void ResizeByPercentage(double pct); // 상위 수준 (추상화에 특화)
}
// "Refined Abstraction"
class CircleShape : IShape
{
private double x, y, radius;
private IDrawingAPI drawingAPI;
public CircleShape(double x, double y, double radius, IDrawingAPI drawingAPI)
{
this.x = x;
this.y = y;
this.radius = radius;
this.drawingAPI = drawingAPI;
}
// 하위 수준 (구현에 특화)
public void Draw() { drawingAPI.DrawCircle(x, y, radius); }
// 상위 수준 (추상화에 특화)
public void ResizeByPercentage(double pct) { radius *= pct; }
}
// "Client"
class BridgePattern
{
public static void Main(string[] args)
{
IShape[] shapes = new IShape[2];
shapes[0] = new CircleShape(1, 2, 3, new DrawingAPI1());
shapes[1] = new CircleShape(5, 7, 11, new DrawingAPI2());
foreach (IShape shape in shapes)
{
shape.ResizeByPercentage(2.5);
shape.Draw();
}
}
}
```
```csharp
// 진정으로 분리된 아키텍처를 제공하는 데 도움
public interface IBridge
{
void Function1();
void Function2();
}
public class Bridge1 : IBridge
{
public void Function1()
{
Console.WriteLine("Bridge1.Function1");
}
public void Function2()
{
Console.WriteLine("Bridge1.Function2");
}
}
public class Bridge2 : IBridge
{
public void Function1()
{
Console.WriteLine("Bridge2.Function1");
}
public void Function2()
{
Console.WriteLine("Bridge2.Function2");
}
}
public interface IAbstractBridge
{
void CallMethod1();
void CallMethod2();
}
public class AbstractBridge : IAbstractBridge
{
public IBridge bridge;
public AbstractBridge(IBridge bridge)
{
this.bridge = bridge;
}
public void CallMethod1()
{
this.bridge.Function1();
}
public void CallMethod2()
{
this.bridge.Function2();
}
}
```
브리지 패턴은 객체를 트리 구조로 구성하며, 추상화와 구현을 분리한다. 여기서 추상화는 객체가 호출될 클라이언트를 나타낸다.
위 코드는 C#으로 구현된 브리지 패턴의 예시이다. 브리지 클래스는 동일한 인터페이스 지향 아키텍처를 사용하여 객체를 생성하는 구현이다. 반면, 추상화는 구현 클래스의 인스턴스를 취하여 해당 메서드를 실행하므로 서로 완전히 분리된다.
4. 3. C++
cpp#include
#include
#include
using namespace std;
// 구현체(Implementor)
class DrawingAPI {
public:
virtual ~DrawingAPI() = default;
virtual string DrawCircle(float x, float y, float radius) const = 0;
};
// 구상 구현체 A(Concrete Implementor A)
class DrawingAPI01 : public DrawingAPI {
public:
string DrawCircle(float x, float y, float radius) const override {
return "API01.circle at " + to_string(x) + ":" + to_string(y) +
" - radius: " + to_string(radius);
}
};
// 구상 구현체 B(Concrete Implementor B)
class DrawingAPI02 : public DrawingAPI {
public:
string DrawCircle(float x, float y, float radius) const override {
return "API02.circle at " + to_string(x) + ":" + to_string(y) +
" - radius: " + to_string(radius);
}
};
// 추상화(Abstraction)
class Shape {
public:
Shape(const DrawingAPI& drawing_api) : drawing_api_(drawing_api) {}
virtual ~Shape() = default;
virtual string Draw() const = 0;
virtual float ResizeByPercentage(const float percent) = 0;
protected:
const DrawingAPI& drawing_api_;
};
// 개선된 추상화(Refined Abstraction)
class CircleShape: public Shape {
public:
CircleShape(float x, float y, float radius, const DrawingAPI& drawing_api)
: Shape(drawing_api), x_(x), y_(y), radius_(radius) {}
string Draw() const override {
return drawing_api_.DrawCircle(x_, y_, radius_);
}
float ResizeByPercentage(const float percent) override {
return radius_ *= (1.0f + percent/100.0f);
}
private:
float x_, y_, radius_;
};
int main(int argc, char** argv) {
const DrawingAPI01 api1{};
const DrawingAPI02 api2{};
vector
CircleShape{1.0f, 2.0f, 3.0f, api1},
CircleShape{5.0f, 7.0f, 11.0f, api2}
};
for (auto& shape: shapes) {
shape.ResizeByPercentage(2.5);
cout << shape.Draw() << endl;
}
return 0;
}
```
출력 결과```text
API01.circle at 1.000000:2.000000 - radius: 3.075000
API02.circle at 5.000000:7.000000 - radius: 11.275000
```
`DrawingAPI`를 통해 원을 그리는 예제이다.
4. 4. Go
gopackage main
import (
"fmt"
)
// DrawingAPI영어 인터페이스는 원을 그리는 기능을 정의한다.
type DrawingAPI interface {
drawCircle(float32, float32, float32)
}
// DrawingAPI1영어은 DrawingAPI영어 인터페이스를 구현하는 구체적인 구조체이다.
type DrawingAPI1 struct{}
func (d *DrawingAPI1) drawCircle(x float32, y float32, radius float32) {
fmt.Printf("API1.circle at %f:%f radius %f\n", x, y, radius)
}
// DrawingAPI2영어는 DrawingAPI영어 인터페이스를 구현하는 또 다른 구조체이다.
type DrawingAPI2 struct{}
func (d *DrawingAPI2) drawCircle(x float32, y float32, radius float32) {
fmt.Printf("API2.circle at %f:%f radius %f\n", x, y, radius)
}
// Shape영어 인터페이스는 그리기와 크기 조절 기능을 정의한다.
type Shape interface {
draw()
resizeByPercentage(float32)
}
// CircleShape영어는 Shape영어 인터페이스를 구현하는 구체적인 원 구조체이다.
type CircleShape struct {
x, y, radius float32
drawingAPI DrawingAPI
}
// draw 메서드는 drawingAPI를 사용하여 원을 그린다.
func (c *CircleShape) draw() {
c.drawingAPI.drawCircle(c.x, c.y, c.radius)
}
// resizeByPercentage 메서드는 원의 반지름을 주어진 비율만큼 조절한다.
func (c *CircleShape) resizeByPercentage(pct float32) {
c.radius *= pct
}
// main 함수는 브리지 패턴의 사용 예시를 보여준다.
func main() {
shape1 := &CircleShape{1, 2, 3, &DrawingAPI1{}}
shape1.resizeByPercentage(2.5)
shape1.draw()
shape2 := &CircleShape{5, 7, 11, &DrawingAPI2{}}
shape2.resizeByPercentage(2)
shape2.draw()
}
4. 5. Python
python# Implementor
class DrawingAPI:
def draw_circle(self, x, y, radius):
pass
# ConcreteImplementor 1/2
class DrawingAPI1(DrawingAPI):
def draw_circle(self, x, y, radius):
print(f"API1.circle at {x}:{y} {radius}")
# ConcreteImplementor 2/2
class DrawingAPI2(DrawingAPI):
def draw_circle(self, x, y, radius):
print(f"API2.circle at {x}:{y} {radius}")
# Abstraction
class Shape:
def draw(self):
pass
def resize_by_percentage(self, pct):
pass
# Refined Abstraction
class CircleShape(Shape):
def __init__(self, x, y, radius, drawing_api):
self.x = x
self.y = y
self.radius = radius
self.drawing_api = drawing_api
def draw(self):
self.drawing_api.draw_circle(self.x, self.y, self.radius)
def resize_by_percentage(self, pct):
self.radius *= pct
def main():
dap1 = DrawingAPI1()
dap2 = DrawingAPI2()
circle1 = CircleShape(1, 2, 3, dap1)
circle2 = CircleShape(5, 7, 11, dap2)
circle1.resize_by_percentage(2.5)
circle2.resize_by_percentage(2.5)
circle1.draw()
circle2.draw()
if __name__ == "__main__":
main()
```
```
브리지 패턴 예제에서는 `DrawingAPI`를 추상화하여 다양한 방식으로 원을 그리는 방법을 보여준다. `DrawingAPI` 인터페이스를 구현하는 `DrawingAPI1`과 `DrawingAPI2` 클래스가 있다. `Shape` 추상 클래스를 상속받는 `CircleShape` 클래스는 `DrawingAPI`를 이용하여 원을 그린다. `main` 함수에서는 `CircleShape` 객체를 생성하고, `resize_by_percentage` 메서드를 통해 크기를 조정한 후, `draw` 메서드를 호출하여 원을 그린다.
4. 6. 기타 언어 (Crystal, PHP, Scala)
crystalabstract class DrawingAPI|추상 클래스 DrawingAPIcr
abstract def draw_circle(x : Float64, y : Float64, radius : Float64)|추상 메소드 draw_circle(x : Float64, y : Float64, radius : Float64)cr
end
class DrawingAPI1 < DrawingAPI
def draw_circle(x : Float, y : Float, radius : Float)
"API1.circle at #{x}:#{y} - radius: #{radius}"
end
end
class DrawingAPI2 < DrawingAPI
def draw_circle(x : Float64, y : Float64, radius : Float64)
"API2.circle at #{x}:#{y} - radius: #{radius}"
end
end
abstract class Shape|추상 클래스 Shapecr
protected getter drawing_api : DrawingAPI
def initialize(@drawing_api)
end
abstract def draw
abstract def resize_by_percentage(percent : Float64)|추상 메소드 resize_by_percentage(percent : Float64)cr
end
class CircleShape < Shape
getter x : Float64
getter y : Float64
getter radius : Float64
def initialize(@x, @y, @radius, drawing_api : DrawingAPI)
super(drawing_api)
end
def draw
@drawing_api.draw_circle(@x, @y, @radius)
end
def resize_by_percentage(percent : Float64)
@radius *= (1 + percent/100)
end
end
class BridgePattern
def self.test
shapes = [] of Shape
shapes << CircleShape.new(1.0, 2.0, 3.0, DrawingAPI1.new)
shapes << CircleShape.new(5.0, 7.0, 11.0, DrawingAPI2.new)
shapes.each do |shape|
shape.resize_by_percentage(2.5)
puts shape.draw
end
end
end
BridgePattern.test
```
출력:
```text
API1.circle at 1.0:2.0 - radius: 3.075
API2.circle at 5.0:7.0 - radius: 11.275
```
```php
interface DrawingAPI|인터페이스 DrawingAPIphp
{
function drawCircle($x, $y, $radius);
}
class DrawingAPI1 implements DrawingAPI
{
public function drawCircle($x, $y, $radius)
{
echo "API1.circle at $x:$y radius $radius.\n";
}
}
class DrawingAPI2 implements DrawingAPI
{
public function drawCircle($x, $y, $radius)
{
echo "API2.circle at $x:$y radius $radius.\n";
}
}
abstract class Shape|추상 클래스 Shapephp
{
protected $drawingAPI;
public abstract function draw();
public abstract function resizeByPercentage($pct);|public 추상 함수 resizeByPercentage($pct);php
protected function __construct(DrawingAPI $drawingAPI)
{
$this->drawingAPI = $drawingAPI;
}
}
class CircleShape extends Shape
{
private $x;
private $y;
private $radius;
public function __construct($x, $y, $radius, DrawingAPI $drawingAPI)
{
parent::__construct($drawingAPI);
$this->x = $x;
$this->y = $y;
$this->radius = $radius;
}
public function draw()
{
$this->drawingAPI->drawCircle($this->x, $this->y, $this->radius);
}
public function resizeByPercentage($pct)
{
$this->radius *= $pct;
}
}
class Tester
{
public static function main()
{
$shapes = array(
new CircleShape(1, 3, 7, new DrawingAPI1()),
new CircleShape(5, 7, 11, new DrawingAPI2()),
);
foreach ($shapes as $shape) {
$shape.resizeByPercentage(2.5);
$shape->draw();
}
}
}
Tester::main();
```
출력:
```text
API1.circle at 1:3 radius 17.5
API2.circle at 5:7 radius 27.5
```
```scala
trait DrawingAPI {
def drawCircle(x: Double, y: Double, radius: Double)
}
class DrawingAPI1 extends DrawingAPI {
def drawCircle(x: Double, y: Double, radius: Double) = println(s"API #1 $x $y $radius")
}
class DrawingAPI2 extends DrawingAPI {
def drawCircle(x: Double, y: Double, radius: Double) = println(s"API #2 $x $y $radius")
}
abstract class Shape(drawingAPI: DrawingAPI) {
def draw()
def resizePercentage(pct: Double)
}
class CircleShape(x: Double, y: Double, var radius: Double, drawingAPI: DrawingAPI)
extends Shape(drawingAPI: DrawingAPI) {
def draw() = drawingAPI.drawCircle(x, y, radius)
def resizePercentage(pct: Double) { radius *= pct }
}
object BridgePattern {
def main(args: Array[String]) {
Seq (
new CircleShape(1, 3, 5, new DrawingAPI1),
new CircleShape(4, 5, 6, new DrawingAPI2)
) foreach { x =>
x.resizePercentage(3)
x.draw()
}
}
}
참조
[1]
웹사이트
The Bridge design pattern - Problem, Solution, and Applicability
http://w3sdesign.com[...]
2017-08-12
[2]
웹사이트
The Bridge design pattern - Structure and Collaboration
http://w3sdesign.com[...]
2017-08-12
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com
